#include "simplericheditor.h"
#include "ui_simplericheditor.h"

#include "QtIconLoader/qticonloader.h"

#include <QTextDocumentFragment>
#include <QTextListFormat>
#include <QTextList>
#include <QToolButton>
#include <QFontComboBox>
#include <QSettings>
#include <QFileInfo>
#include <QFileDialog>
#include <QMessageBox>
#include <QDir>
#include <QDebug>

const int INDENT_PX = 40;

SimpleRichEditor::SimpleRichEditor(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SimpleRichEditor)
{
    ui->setupUi(this);

    createStandardToolbar();

    connect(ui->textBrowser, SIGNAL(cursorPositionChanged()), SLOT(updateFormatButtons()));
    connect(ui->textBrowser, SIGNAL(cursorPositionChanged()), SLOT(updateFontCombo()));

    //connect(ui->textBrowser, SIGNAL(currentCharFormatChanged(QTextCharFormat)), SLOT(update))
}

SimpleRichEditor::~SimpleRichEditor()
{
    delete ui;
}

/// *** PUBLIC API *** ///
QVariant SimpleRichEditor::data() const
{
    return QVariant(ui->textBrowser->toHtml());
}

void SimpleRichEditor::setData(QVariant data)
{
    ui->textBrowser->setHtml(data.toString());
}

void SimpleRichEditor::createStandardToolbar()
{
    QList<QToolButton*> buttons;
    QHBoxLayout* hbox = new QHBoxLayout(ui->frToolbar);

    /// *** EDIT *** ///
    // CLEAR
    buttons << addToolButton("edit-clear", SLOT(clear()), ui->textBrowser);
    // COPY
    buttons << addToolButton("edit-copy", SLOT(copy()), ui->textBrowser);
    // CUT
    buttons << addToolButton("edit-cut", SLOT(cut()), ui->textBrowser);
    // PASTE
    buttons << addToolButton("edit-paste", SLOT(paste()), ui->textBrowser);

    buttons << 0;

    /// *** FORMAT *** ///
    buttons << addToolButton("format-indent-less", SLOT(formatIndentLess()));
    buttons << addToolButton("format-indent-more", SLOT(formatIndentMore()));
    buttons << addToolButton("format-justify-left", SLOT(formatJustifyLeft()));
    buttons << addToolButton("format-justify-center", SLOT(formatJustifyCenter()));
    buttons << addToolButton("format-justify-right", SLOT(formatJustifyRight()));
    buttons << addToolButton("format-justify-fill", SLOT(formatJustifyFill()));

    tbBold      = addToolButton("format-text-bold", SLOT(formatTextBold(bool)), this, true);
    tbItalic    = addToolButton("format-text-italic", SLOT(setFontItalic(bool)), ui->textBrowser, true);
    tbUnderLine = addToolButton("format-text-underline", SLOT(setFontUnderline(bool)), ui->textBrowser, true);
    buttons << tbBold << tbItalic << tbUnderLine;

    buttons << 0;

    /// *** INSERT *** ///
    //buttons << addToolButton("insert-image", SLOT(insertImage()));
    buttons << addToolButton("insert-link", SLOT(insertLink()));
    buttons << addToolButton("list-enum", SLOT(listEnum()));
    buttons << addToolButton("list-bullet", SLOT(listBullet()));

    foreach(QToolButton* tb, buttons)
    {
        if ( tb == 0 )
            hbox->addSpacing(50);
        else
            hbox->addWidget(tb);
    }

    hbox->addSpacing(50);

    /// *** FONT COMBOBOX *** ///
    cbFonts = new QFontComboBox(this);
    connect(cbFonts, SIGNAL(activated(QString)), ui->textBrowser, SLOT(setFontFamily(QString)));
    hbox->addWidget(cbFonts);

    /// *** FONT COMBOBOX *** ///
    cbFontSizes = new QComboBox(this);
    for(int i = 6; i <= 16; ++i )
        cbFontSizes->addItem(QString::number(i));
    for(int i = 18; i <= 96; i+=2)
        cbFontSizes->addItem(QString::number(i));
    connect(cbFontSizes, SIGNAL(activated(QString)), SLOT(setCurrentFontSize(QString)));
    hbox->addWidget(cbFontSizes);

    hbox->setMargin(5);
    hbox->setSpacing(1);
    ui->frToolbar->setLayout(hbox);
}

QToolButton* SimpleRichEditor::addToolButton(QString iconText, const char* slot, QObject* dest, bool toggle)
{
    QToolButton* tb = new QToolButton(this);

    qDebug() << "Fallback to: " << ":/icons/"+iconText+".png";

    tb->setIcon(QtIconLoader::icon(iconText, QIcon(":/icons/"+iconText+".png")));
    tb->setCheckable(toggle);
    connect(tb, toggle ? SIGNAL(toggled(bool)) : SIGNAL(clicked()), dest ? dest : this, slot);
    return tb;
}

void SimpleRichEditor::updateBulletList(QTextCursor* cursor, QTextBlockFormat* blockFmt)
{
    QTextListFormat listFmt = cursor->currentList()->format();
    QTextListFormat::Style style =
            blockFmt->indent() == 0 ? QTextListFormat::ListDisc
                                   : blockFmt->indent() == 1 ? QTextListFormat::ListCircle
                                   : QTextListFormat::ListSquare;
    listFmt.setStyle(style);
    cursor->createList(listFmt);
}

void SimpleRichEditor::updateEnumList(QTextCursor* cursor, QTextBlockFormat* blockFmt)
{
    Q_UNUSED(blockFmt);

    QTextListFormat listFmt = cursor->currentList()->format();
    QTextListFormat::Style style = QTextListFormat::ListDecimal;
    listFmt.setStyle(style);
    cursor->createList(listFmt);
}

// *** SLOTS *** ///

void SimpleRichEditor::formatIndentLess()
{
    QTextCursor cursor(ui->textBrowser->textCursor());
    QTextBlockFormat blockFmt = cursor.blockFormat();
    if ( blockFmt.indent() <= 0 )
        return;

    blockFmt.setIndent(blockFmt.indent()-1);

    cursor.beginEditBlock();
    cursor.setBlockFormat(blockFmt);

    if ( cursor.currentList() )
    {
        QTextBlockFormat bfmt;
        bfmt.setObjectIndex(-1);
        cursor.mergeBlockFormat(bfmt);


        /*        if ( cursor.currentList()->format().style() == QTextListFormat::ListDecimal )
            updateEnumList(&cursor, &blockFmt);
        else
            updateBulletList(&cursor, &blockFmt);*/
    }

    cursor.endEditBlock();
}

void SimpleRichEditor::formatIndentMore()
{
    QTextCursor cursor(ui->textBrowser->textCursor());
    QTextBlockFormat blockFmt = cursor.blockFormat();
    blockFmt.setIndent(blockFmt.indent()+1);

    cursor.beginEditBlock();
    cursor.setBlockFormat(blockFmt);
    if ( cursor.currentList() )
    {
        if ( cursor.currentList()->format().style() == QTextListFormat::ListDecimal )
            updateEnumList(&cursor, &blockFmt);
        else
            updateBulletList(&cursor, &blockFmt);
    }


    cursor.endEditBlock();
}

void SimpleRichEditor::formatJustifyLeft()
{
    ui->textBrowser->setAlignment(Qt::AlignLeft);
}

void SimpleRichEditor::formatJustifyCenter()
{
    ui->textBrowser->setAlignment(Qt::AlignCenter);
}

void SimpleRichEditor::formatJustifyRight()
{
    ui->textBrowser->setAlignment(Qt::AlignRight);
}

void SimpleRichEditor::formatJustifyFill()
{
    ui->textBrowser->setAlignment(Qt::AlignJustify);
}

void SimpleRichEditor::formatTextBold(bool flag)
{
    ui->textBrowser->setFontWeight(flag ? QFont::Bold : 0);
}

void SimpleRichEditor::insertImage()
{
    QSettings settings;
    QString folder(settings.value("last_opensave_folder", QDir::homePath()).toString());
    QString fileName = QFileDialog::getOpenFileName(this,
                                                    tr("Choose Image"),
                                                    QDir::toNativeSeparators(folder),
                                                    tr("Images (*.png *.jpg *.jpeg *.gif *.bmp)"));

    if ( fileName.isEmpty() )
        return;

    settings.setValue("last_opensave_folder",
                      QFileInfo(fileName).absolutePath());

    QImage base(fileName);
    if ( base.isNull() )
    {
        QMessageBox::warning(this, qApp->applicationName(), tr("Image file not supported."));
        //RedirectToUrl( QUrl(fileimg) );
        return;
    }

    insertImage(fileName);
}

void SimpleRichEditor::insertImage(QString file_or_url)
{
    QString subtext = QString("<p><img src=\"%1\" />").arg(file_or_url);
    QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(subtext);
    ui->textBrowser->textCursor().insertFragment(fragment);
}

void SimpleRichEditor::listEnum()
{
    QTextCursor cursor(ui->textBrowser->textCursor());
    QTextListFormat::Style style = QTextListFormat::ListDecimal;

    cursor.beginEditBlock();
    QTextBlockFormat blockFmt = cursor.blockFormat();
    QTextListFormat listFmt;

    if (cursor.currentList())
    {
        listFmt = cursor.currentList()->format();
    }
    else
    {
        listFmt.setIndent(blockFmt.indent() + 1);
        blockFmt.setIndent(0);
        cursor.setBlockFormat(blockFmt);
    }

    listFmt.setStyle(style);
    cursor.createList(listFmt);
    cursor.endEditBlock();
}

void SimpleRichEditor::listBullet()
{
    QTextCursor cursor(ui->textBrowser->textCursor());
    QTextBlockFormat blockFmt = cursor.blockFormat();
    QTextListFormat::Style style =
            blockFmt.indent() == 0 ? QTextListFormat::ListDisc
                                   : blockFmt.indent() == 1 ? QTextListFormat::ListCircle
                                   : QTextListFormat::ListSquare;

    cursor.beginEditBlock();
    QTextListFormat listFmt;

    if (cursor.currentList())
    {
        listFmt = cursor.currentList()->format();
    }
    else
    {
        listFmt.setIndent(blockFmt.indent() + 1);
        blockFmt.setIndent(0);
        cursor.setBlockFormat(blockFmt);
    }

    listFmt.setStyle(style);
    cursor.createList(listFmt);
    cursor.endEditBlock();
}

void SimpleRichEditor::updateFormatButtons()
{
    tbBold->setChecked(ui->textBrowser->fontWeight() >= QFont::Bold );
    tbItalic->setChecked(ui->textBrowser->fontItalic());
    tbUnderLine->setChecked(ui->textBrowser->fontUnderline());
}

void SimpleRichEditor::updateFontCombo()
{
    QFont font = ui->textBrowser->currentFont();
    cbFonts->setCurrentFont(font);
    cbFontSizes->setCurrentIndex(cbFontSizes->findText(QString::number(font.pointSize())));
}

void SimpleRichEditor::setCurrentFontSize(QString value)
{
    bool ok = false;
    qreal size = value.toFloat(&ok);
    if ( ok )
        ui->textBrowser->setFontPointSize(size);
}
